#pragma once

#include "map/gridmap.h"
#include "map/griddefines.h"

class TerrainInfo
{
public:
    TerrainInfo(unsigned int mapid);
    ~TerrainInfo();

    unsigned int GetMapId() const { return m_mapId; }

    // TODO: move all terrain/vmaps data info query functions
    // from 'Map' class into this class
    float GetHeightStatic(float x, float y, float z, bool checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const;
    float GetWaterLevel(float x, float y, float z, float* pGround = NULL) const;
    float GetWaterOrGroundLevel(float x, float y, float z, float* pGround = NULL, bool swim = false) const;
    bool IsInWater(float x, float y, float z, GridMapLiquidData* data = 0) const;
    bool IsSwimmable(float x, float y, float pZ, float radius = 1.5f, GridMapLiquidData* data = 0) const;
    bool IsUnderWater(float x, float y, float z) const;

    GridMapLiquidStatus getLiquidStatus(float x, float y, float z, unsigned char ReqLiquidType, GridMapLiquidData* data = 0) const;

    unsigned short GetAreaFlag(float x, float y, float z, bool* isOutdoors = 0) const;
    unsigned char GetTerrainType(float x, float y) const;

    unsigned int GetAreaId(float x, float y, float z) const;
    unsigned int GetZoneId(float x, float y, float z) const;
    void GetZoneAndAreaId(unsigned int& zoneid, unsigned int& areaid, float x, float y, float z) const;

    bool GetAreaInfo(float x, float y, float z, unsigned int& mogpflags, int& adtId, int& rootId, int& groupId) const;
    bool IsOutdoors(float x, float y, float z) const;


    // this method should be used only by TerrainManager
    // to cleanup unreferenced GridMap objects - they are too heavy
    // to destroy them dynamically, especially on highly populated servers
    // THIS METHOD IS NOT THREAD-SAFE!!!! AND IT SHOULDN'T BE THREAD-SAFE!!!!
    void CleanUpGrids(const unsigned int diff);

#if 1
    void AddRef() {}
    bool Release() { return true; };
#endif
protected:
    friend class Map;
    // load/unload terrain data
    GridMap* Load(const unsigned int x, const unsigned int y);
    void Unload(const unsigned int x, const unsigned int y);

private:
    TerrainInfo(const TerrainInfo&);
    TerrainInfo& operator=(const TerrainInfo&);

    GridMap* GetGrid(const float x, const float y);
    GridMap* LoadMapAndVMap(const unsigned int x, const unsigned int y);

    int RefGrid(const unsigned int& x, const unsigned int& y);
    int UnrefGrid(const unsigned int& x, const unsigned int& y);

    const unsigned int m_mapId;

    GridMap* m_GridMaps[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS];
    short m_GridRef[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS];

#if 0
    // global garbage collection timer
    IntervalTimer i_timer;

    typedef ACE_Thread_Mutex LOCK_TYPE;
    LOCK_TYPE m_mutex;
    char _cache_guard[1024];
    LOCK_TYPE m_refMutex;
#endif
};
